package deployr.core;

import static deployr.core.Streams.*;

import java.io.*;
import java.util.*;

public class FileSystem {

	private final File root;

	public FileSystem(File root) {
		this.root = root;
		root.mkdirs();
	}

	public File mkdirs(String relativePath) {
		File absolute = mkAbsolute(relativePath);
		absolute.mkdirs();
		return absolute;
	}

	public void put(String relativePath, String string) {
		put(relativePath, string.getBytes());
	}

	private File mkAbsolute(String relativePath) {
		File absolute = file(root, relativePath);
		absolute.getParentFile().mkdirs();
		return absolute;
	}

	public void put(String relativePath, byte[] bytes) {
		Streams.copy(bytes, mkAbsolute(relativePath));
	}

	public List<String> find(String relativePath, final String name) {
		File start = mkAbsolute(relativePath);
		List<String> result = new LinkedList<String>();
		find(root, name, start, result);
		return result;
	}

	private void find(File root, String name, File dir, List<String> result) {
		if (null == dir) return;
		if (!dir.exists()) return;
		for (File current : dir.listFiles()) {
			if (current.isDirectory()) {
				find(root, name, current, result);
			}
			if (current.getName().equals(name)) {
				result.add(current.getPath().replaceAll(root.getPath(), ""));
			}
		}
	}

	public InputStream read(String relativePath) {
		return inputStream(mkAbsolute(relativePath));
	}

	public boolean exist(String relativePath) {
		File file = mkAbsolute(relativePath);
		return file.exists();
	}

	public void delete(String relativePath) {
		File file = mkAbsolute(relativePath);
		delete(file);
	}

	private void delete(File file) {
		if (file.isDirectory()) {
			for (File child : file.listFiles()) {
				delete(child);
			}
		}
		file.delete();
	}

	public File getFile() {
		return root;
	}

	public void copy(InputStream inputStream, String relativePath) {
		Streams.copy(inputStream, outputStream(mkAbsolute(relativePath)));
	}

	public String absolutePath(String relativePath) {
		return mkAbsolute(relativePath).getAbsolutePath();
	}

	public File get(String relativePath) {
		return mkAbsolute(relativePath);
	}

}
